import { shallowMount } from '@vue/test-utils';
import { GlAlert, GlModal } from '@gitlab/ui';
import { getCookie, setCookie } from '~/lib/utils/common_utils';
import { stubComponent } from 'helpers/stub_component';
import AgentVulnerabilityReport from 'ee/security_dashboard/components/agent/agent_vulnerability_report.vue';
import VulnerabilityReport from 'ee/security_dashboard/components/shared/vulnerability_report/vulnerability_report.vue';
import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
import { trackAgentSecurityTabAlert } from 'ee/security_dashboard/components/agent/constants';

import {
  FIELD_PRESETS,
  FILTER_PRESETS,
} from 'ee/security_dashboard/components/shared/vulnerability_report/constants';

jest.mock('~/lib/utils/common_utils', () => ({
  parseBoolean: jest.requireActual('~/lib/utils/common_utils').parseBoolean,
  getCookie: jest.fn().mockReturnValue(false),
  setCookie: jest.fn(),
}));

describe('Agent vulnerability report component', () => {
  let wrapper;
  let showMock;

  const propsData = { clusterAgentId: 'gid://gitlab/Clusters::Agent/1' };
  const provide = { agentName: 'primary-agent', projectPath: '/path/to/project/' };

  const findAlert = () => wrapper.findComponent(GlAlert);
  const findReport = () => wrapper.findComponent(VulnerabilityReport);
  const findModal = () => wrapper.findComponent(GlModal);
  const createWrapper = () => {
    showMock = jest.fn();

    wrapper = shallowMount(AgentVulnerabilityReport, {
      propsData,
      provide,
      stubs: {
        GlModal: stubComponent(GlModal, {
          methods: { show: showMock },
        }),
      },
    });
  };

  describe('default', () => {
    beforeEach(() => {
      createWrapper();
    });

    it('passes the expected props to the vulnerability report component', () => {
      expect(findReport().props()).toMatchObject({
        fields: FIELD_PRESETS.AGENT,
        filterDropdowns: FILTER_PRESETS.AGENT,
        filterFn: wrapper.vm.transformFilters,
      });
    });

    it('shows the vulnerability alert if there is no cookie', () => {
      expect(findAlert().exists()).toBe(true);
    });

    it('opens the modal when a user dismisses the alert', async () => {
      expect(showMock).not.toHaveBeenCalled();

      await findAlert().vm.$emit('dismiss');

      expect(showMock).toHaveBeenCalled();
    });

    it('sets the cookie when a user verifies they do not want to view the alert', () => {
      expect(setCookie).not.toHaveBeenCalled();
      findAlert().vm.$emit('dismiss');

      findModal().vm.$emit('primary');

      expect(setCookie).toHaveBeenCalled();
    });

    describe('snowplow tracking', () => {
      afterEach(() => {
        unmockTracking();
      });

      it('tracks the Snowplow event when a user verifies they do not want to view the alert', () => {
        const { category, action } = trackAgentSecurityTabAlert;
        const trackingSpy = mockTracking(category, wrapper.element, jest.spyOn);
        expect(trackingSpy).not.toHaveBeenCalled();
        findAlert().vm.$emit('dismiss');
        findModal().vm.$emit('primary');
        expect(trackingSpy).toHaveBeenCalledWith(category, action);
      });
    });
  });

  it('hides the vulnerability alert if there is a cookie', () => {
    getCookie.mockImplementationOnce(() => true);
    createWrapper();

    expect(findAlert().exists()).toBe(false);
  });
});
